﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace engine
{
    #region Word解析树节点
    public class DocumentNode : NodeBase
    {
        public List<TextBoxNode> TextBoxes { get; set; }

        public override bool JustSource
        {
            get
            {
                bool result = true;
                if (FuncNode != null || MustRender)
                {
                    result = false;
                }
                else
                {
                    foreach (var child in Children)
                    {
                        if (!child.JustSource)
                        {
                            result = false;
                        }
                    }
                    foreach (var child in TextBoxes)
                    {
                        if (!child.JustSource)
                        {
                            result = false;
                        }
                    }
                }
                return result;
            }
        }

        public DocumentNode(object source) : base(UnitType.Body, source)
        {
            TextBoxes = new List<TextBoxNode>();
        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            DocumentUnit document = new DocumentUnit();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    document.AddChild(unit);
                }
            }
            foreach(var textBox in TextBoxes)
            {
                var units = textBox.RenderValue(rt);
                foreach(var unit in units)
                {
                    document.TextBoxs.Add(unit as TextBoxUnit);
                }
            }
            return new List<Unit>
            {
                document
            };
        }

        // 匹配数据应该也重写
        protected override void CustomMatchData(Unit unit, FuncNode rootFuncNode, EngineRuntime rt)
        {
            foreach (var child in Children)
            {
                child.MatchData(unit.Children, rootFuncNode, rt);
            }

            var unitTextBoxs = (unit as DocumentUnit).TextBoxs.ToList<Unit>();
            foreach(var textBox in TextBoxes)
            {
                textBox.MatchData(unitTextBoxs, rootFuncNode, rt);
            }
        }
    }

    public class SectionNode : NodeBase
    {
        public SectionNode(object source) : base(UnitType.Body, source)
        {
            ContainerType = ContainerType.Body;
        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            SectionUnit section = new SectionUnit();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    section.AddChild(unit);
                }
            }
            return new List<Unit>
            {
                section
            };
        }
    }
    #endregion

    #region Excel解析树节点
    public class WorkbookNode : NodeBase
    {
        public WorkbookNode(object source)
            : base(UnitType.Body, source)
        {

        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            WorkbookUnit result = new WorkbookUnit();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    result.AddChild(unit);
                }
            }
            return new List<Unit>
            {
                result
            };
        }
    }

    public class WorksheetNode : NodeBase
    {
        public TableNode Table { get; set; }
        public List<TextBoxNode> TextBoxes { get; set; }
        public List<PictureNode> Pictures { get; set; }

        public override bool JustSource
        {
            get
            {
                bool result = true;
                if (FuncNode != null || MustRender)
                {
                    result = false;
                }
                else
                {
                    foreach (var child in Table.Rows)
                    {
                        if (!child.JustSource)
                        {
                            result = false;
                        }
                    }
                    foreach (var child in TextBoxes)
                    {
                        if (!child.JustSource)
                        {
                            result = false;
                        }
                    }
                    foreach (var child in Pictures)
                    {
                        if (!child.JustSource)
                        {
                            result = false;
                        }
                    }
                }
                return result;
            }
        }

        public WorksheetNode(object source)
            : base(UnitType.Body, source)
        {
            Table = new TableNode(source);
            TextBoxes = new List<TextBoxNode>();
            Pictures = new List<PictureNode>();
        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            WorksheetUnit result = new WorksheetUnit();

            result.Table = Table.RenderValue(rt).FirstOrDefault() as TableUnit;

            foreach (var textbox in TextBoxes)
            {
                var units = textbox.RenderValue(rt);
                foreach (var unit in units)
                {
                    result.TextBoxs.Add(unit as TextBoxUnit);
                }
            }
            
            foreach (var picture in Pictures)
            {
                var units = picture.RenderValue(rt);
                foreach (var unit in units)
                {
                    result.Pictures.Add(unit as PictureUnit);
                }
            }

            return new List<Unit>
            {
                result
            };
        }
    }
    #endregion

    #region PowerPoint解析树节点
    public class PresentationNode : NodeBase
    {
        public PresentationNode(object source)
            : base(UnitType.Body, source)
        {

        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            WorkbookUnit result = new WorkbookUnit();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    result.AddChild(unit);
                }
            }
            return new List<Unit>
            {
                result
            };
        }
    }

    public class SlideNode : NodeBase
    {
        public SlideNode(object source, object sourceParent = null)
            : base(UnitType.Body, source, sourceParent)
        {

        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            WorkbookUnit result = new WorkbookUnit();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    result.AddChild(unit);
                }
            }
            return new List<Unit>
            {
                result
            };
        }
    }
    #endregion

    #region NodeBase 通用解析树节点
    public class TextBoxNode : NodeBase
    {
        public TextBoxNode(object source, object sourceParent = null) : base(UnitType.Body, source, sourceParent)
        {
        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            TextBoxUnit textbox = new TextBoxUnit();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    textbox.AddChild(unit);
                }
            }
            return new List<Unit>
            {
                textbox
            };
        }
    }

    public class TableNode : NodeBase
    {
        public TableNode(object source, object sourceParent = null) : base(UnitType.Table, source, sourceParent)
        {
            ContainerType = ContainerType.Body;
        }

        public List<RowNode> Rows
        {
            get
            {
                return Children.Select(r => r as RowNode).ToList();
            }
        }

        public int ColumnCount { get; set; }

        public void AddRow(RowNode rowNode)
        {
            if (rowNode.Children.Count != ColumnCount)
            {
                throw new Exception("行的单元格树不正确");
            }
            else
            {
                AddChild(rowNode);
            }
        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            TableUnit table = new TableUnit();
            foreach (var child in Children)
            {
                var rows = child.RenderValue(rt);
                foreach (var row in rows)
                {
                    table.Rows.Add(row as RowUnit);
                }
            }
            return new List<Unit>
            {
                table
            };
        }
    }

    public class RowNode : NodeBase
    {
        public RowNode(object source, object sourceParent = null) : base(UnitType.Row, source, sourceParent) { }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            RowUnit row = new RowUnit();
            foreach (var child in Children)
            {
                var cells = child.RenderValue(rt);
                foreach (var cell in cells)
                {
                    row.Cells.Add(cell);
                }
            }
            return new List<Unit>
            {
                row
            };
        }
    }

    public class CellNode : NodeBase
    {
        public CellNode(object source, object sourceParent = null) : base(UnitType.Cell|UnitType.Body, source, sourceParent)
        {
        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            CellUnit cell = new CellUnit();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    cell.AddChild(unit);
                }
            }
            return new List<Unit>
            {
                cell
            };
        }
    }

    public class BodyNode : NodeBase
    {
        public BodyNode(object source, object sourceParent = null) : base(UnitType.Body, source, sourceParent) { }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            var result = new List<Unit>();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    result.Add(unit);
                }
            }
            return result;
        }
    }

    public class ParagraphNode : NodeBase
    {
        public ParagraphNode(object source, object sourceParent = null) : base(UnitType.Paragraph, source, sourceParent)
        {
            ContainerType = ContainerType.Body;
        }

        public override void AddChild(NodeBase child)
        {
            if(child is TextRangeNode && string.IsNullOrWhiteSpace((child as TextRangeNode).Text))
            {
                var temp = child as TextRangeNode;
                if(string.IsNullOrWhiteSpace(temp.Text) && temp.FuncNode == null)
                {
                    return;
                }
            }
            base.AddChild(child);
        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            ParagraphUnit paragraph = new ParagraphUnit();
            foreach (var child in Children)
            {
                var units = child.RenderValue(rt);
                foreach (var unit in units)
                {
                    paragraph.AddChild(unit);
                }
            }
            return new List<Unit>
            {
                paragraph
            };
        }
    }

    public class TextRangeNode : NodeBase
    {
        public string Text { get; set; }
        public CharactorFormat CharactorFormat { get; set; }

        public TextRangeNode(string text, object source, object sourceParent = null) : base(UnitType.TextRange, source, sourceParent)
        {
            Text = text;
        }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            //throw new Exception("TextRangeNode节点没有子节点可以渲染");
            TextRangeUnit unit = new TextRangeUnit();
            unit.Text = Text;
            return new List<Unit>
            {
                unit
            };
        }
    }

    public class PictureNode : NodeBase
    {
        public Image Image { get; set; }

        public PictureNode(object source, object sourceParent = null) : base(UnitType.Picture, source, sourceParent) { }

        protected override List<Unit> CustomRender(EngineRuntime rt)
        {
            //throw new Exception("PictureNode节点没有子节点可以渲染");
            PictureUnit unit = new PictureUnit();
            unit.Image = Image;
            return new List<Unit>
            {
                unit
            };
        }
    }

    public enum ContainerType
    {
        String,
        FullString,
        Body
    }

    public abstract class NodeBase : ConvertibleBase
    {
        /// <summary>
        /// 源对象
        /// </summary>
        public object Source { get; set; }
        public object SourceParent { get; set; }
        public virtual bool JustSource
        {
            get
            {
                bool result = true;
                if(FuncNode != null || MustRender)
                {
                    result = false;
                }
                else
                {
                    foreach(var child in Children)
                    {
                        if (!child.JustSource)
                        {
                            result = false;
                        }
                    }
                }
                return result;
            }
        }
        public bool MustRender { get; set; }

        public UnitType? MappedUnitType { get; set; }
        public ContainerType ContainerType { get; protected set; }
        public FuncNode FuncNode { get; set; }

        public virtual List<NodeBase> Children { get; set; }
        public NodeBase Parent { get; set; }
        public NodeBase Prev { get; set; }
        public NodeBase Next { get; set; }

        public NodeBase(UnitType? unitType, object source, object sourceParent = null)
        {
            MappedUnitType = unitType;
            Source = source;
            SourceParent = sourceParent;
            Children = new List<NodeBase>();
        }

        public virtual void AddChild(NodeBase child)
        {
            NodeBase prev = Children.LastOrDefault();
            if (prev != null)
            {
                child.Prev = prev;
                prev.Next = child;
            }
            Children.Add(child);
            child.Parent = this;
        }

        protected abstract List<Unit> CustomRender(EngineRuntime rt);

        public virtual List<Unit> RenderValue(EngineRuntime rt)
        {
            List<Unit> result = null;
            if (FuncNode != null)
            {
                var temp = FuncNode.Run(this, rt);

                if (temp is List<Unit>)
                {
                    result = temp as List<Unit>;// 传值source
                }
                else if(temp is Unit)
                {
                    result = new List<Unit> { temp as Unit };
                }
                else
                {
                    var units = new List<Unit>();
                    var textRangeUnit = new TextRangeUnit();
                    textRangeUnit.Text = temp.ToString();
                    units.Add(textRangeUnit);
                    result = units;
                }
            }
            else
            {
                result = CustomRender(rt);
            }

            bool justSource = JustSource;
            foreach(var e in result)
            {
                e.Source = Source;
                e.SourceParent = SourceParent;
                e.JustSource = justSource;
            }

            return result;
        }

        protected virtual void CustomMatchData(Unit unit, FuncNode rootFuncNode, EngineRuntime rt)
        {
            foreach (var child in Children)
            {
                child.MatchData(unit.Children, rootFuncNode, rt);
            }
        }

        public void MatchData(List<Unit> units, FuncNode rootFuncNode, EngineRuntime rt)
        {
            if (units == null)
            {
                return;
            }

            var notMatched = units.Where(r => r.MatchStatus == MatchStatus.None).ToList();

            if (notMatched.Count == 0)
            {
                return;
            }

            if (FuncNode != null)
            {
                FuncNode.RunForMatch(this, notMatched, rt);
            }
            else
            {
                var temp = notMatched[0];
                CustomMatchData(temp, rootFuncNode, rt);

                if(temp is TextRangeUnit || temp is PictureUnit)
                {

                }
                else
                {
                    temp.MatchStatus = MatchStatus.Matched;
                }
            }
        }

        /// <summary>
        /// 得到当前所处的函数环境
        /// </summary>
        /// <param name="rootFuncNode"></param>
        /// <returns></returns>
        public FuncNode GetCurrentFuncNode(FuncNode rootFuncNode = null)
        {
            if(rootFuncNode != null && rootFuncNode.Parent != null)
            {
                return rootFuncNode;
            }

            if(FuncNode != null)
            {
                return FuncNode;
            }
            else
            {
                if(Parent != null)
                {
                    return Parent.GetCurrentFuncNode(rootFuncNode);
                }
                else
                {
                    return rootFuncNode;
                }
            }
        }
    }
    #endregion
}
